﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SiGeSIB.Data.Common;
using SiGeSIB.GUI.Common.DedaGrid.Utils;
using SiGeSIB.GUI.Common.DedaGrid;

namespace SiGeSIB.GUI.Common
{
	public abstract partial class FGenericManager<T> : ConflictableForm, IRefreshable, IStateModifier where T : class
	{
		public FGenericManager()
		{
			InitializeComponent();

			#region ToolStrip Step
			uManageDefaultToolStrip.ExitClicked += new EventHandler(uManageDefaultToolStrip_ExitClicked);
			uManageDefaultToolStrip.SearchTextChanged += new EventHandler<EventArgs<string>>(uManageDefaultToolStrip_SearchTextChanged);
			uManageDefaultToolStrip.AddClicked += new EventHandler(uManageDefaultToolStrip_AddClicked);
			uManageDefaultToolStrip.EditClicked += new EventHandler(uManageDefaultToolStrip_EditClicked);
			uManageDefaultToolStrip.RemoveClicked += new EventHandler(uManageDefaultToolStrip_RemoveClicked);
			uManageDefaultToolStrip.ReloadClicked += new EventHandler(uManageDefaultToolStrip_ReloadClicked); 
			#endregion

			#region Controller
			_Controller = new FormController(defaultStatusBar1);
			_Controller.BusyStateChanged += new EventHandler(_Controler_BusyStateChanged);

			_Controller.FieldsToLock.AddRange
				(
					new List<object>()
					{
						uManageDefaultToolStrip,
						panel1
					}
				);
			#endregion

			#region OtherSteps
			this.LoadDataCompleted += new EventHandler(OnLoadDataCompleted);
			uEntitiesGrid.SelectionChanged += new EventHandler(OnSelectionChanged);
			#endregion
		}

		#region Attributes
		protected const string DT_ID = "Id";
		protected const string DT_ITEM_HOLDER = "ItemHolder";
		protected List<T> _CurrentEntities;
		protected FormController _Controller;
		protected DataTable _DtTable;
		protected List<DedaGridColumn> _DedaColumns;
		protected List<string> _GroupedColumns;
		protected Manager _Manager = Manager.Instance;
		protected string _IdleMessage;
		#endregion

		#region Properties
		protected abstract string _Description { get; }
		#endregion

		#region Events Handler
		protected void uManageDefaultToolStrip_SearchTextChanged(object sender, SiGeSIB.EventArgs<string> e)
		{
			if (_DtTable != null)
				_ApplyFilter(e.Args);
		}
		protected void uManageDefaultToolStrip_ExitClicked(object sender, EventArgs e)
		{
			if (RequestClose != null)
				RequestClose(this, new EventArgs<DialogResult>(DialogResult.OK));
		}
		protected abstract void uManageDefaultToolStrip_AddClicked(object sender, EventArgs e);
		protected abstract void uManageDefaultToolStrip_EditClicked(object sender, EventArgs e);
		protected void uManageDefaultToolStrip_RemoveClicked(object sender, EventArgs e)
		{
			DataRow dr = uEntitiesGrid.GetSelectedRow();
			int entityId = (int)dr[DT_ID];

			_Remove(entityId);
		}
		protected void uManageDefaultToolStrip_ReloadClicked(object sender, EventArgs e)
		{
			_LoadData();
		}
		protected virtual void OnSelectionChanged(object sender, EventArgs args)
		{
			_RefreshUIState();
		}
		private void _Controler_BusyStateChanged(object sender, EventArgs e)
		{
			_RefreshUIState();

			if (!_Controller.IsBusy)
				_Controller.DisplayIdleMessage(_IdleMessage);
			else
				_Controller.DisplayIdleMessage("Aguarde. Carregando...");
		}
		#endregion

		#region Methods
		#region LoadData
		protected EventHandler LoadDataCompleted;
		protected virtual void OnLoadDataCompleted(object sender, EventArgs args)
		{
			_CreateDataTable();

			_FillEntities();

			uEntitiesGrid.SetDataBinding(_DtTable, _GroupedColumns);
		}

		protected abstract void _InitializeDataColumns();
		protected void _LoadData()
		{
			_Controller.ClearErrors();
			if (!_Controller.IsBusy)
			{
				_Controller.EnableBusy();
				bw_LoadData.RunWorkerAsync();
			}
		}
		private void bw_LoadData_DoWork(object sender, DoWorkEventArgs e)
		{
			e.Result = _LoadEntity();
		}
		private void bw_LoadData_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
		{
			if (!IsDisposed)
			{
				if (e.Error == null)
				{
					_CurrentEntities = e.Result as List<T>;

					if (LoadDataCompleted != null)
						LoadDataCompleted(this, new EventArgs());
					
					_Controller.DisableBusy();
				}
				else
				{
					_Controller.DisableBusy();
					_Controller.LoadError(e.Error);
				}
			}
		}

		protected virtual void _FillEntities()
		{
			if (_CurrentEntities != null)
				foreach (T obj in _CurrentEntities)
					_DtTable.Rows.Add(_ConvertToDataRow(obj));
		}
		protected abstract object[] _ConvertToDataRow(T obj);
		#endregion

		#region Remove
		private void _Remove(int id)
		{
			_Controller.ClearErrors();
			if (_RequestRemove() && !_Controller.IsBusy)
			{
				_Controller.EnableBusy();
				bwRemove.RunWorkerAsync(id);
			}
		}

		private void bwRemove_DoWork(object sender, DoWorkEventArgs e)
		{
			_RemoveEntity((int)e.Argument);
		}
		private void bwRemove_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
		{
			if (!IsDisposed)
			{
				_Controller.DisableBusy();

				if (e.Error == null)
				{
					_LoadData();
				}
				else
					_Controller.LoadError(e.Error);
			}
		} 
		#endregion
		#endregion

		#region Abstract and virtual methods
		protected override void OnLoad(EventArgs e)
		{
			base.OnLoad(e);

			_IdleMessage = string.Concat("Listando ", _Description);
			_Controller.DisplayIdleMessage(_IdleMessage);

#if !DESIGN
			_InitializeDataColumns();

			_LoadData();
#endif
		}

		protected virtual void _RefreshUIState()
		{
			DataRow row = uEntitiesGrid.GetSelectedRow();
			uManageDefaultToolStrip.RefreshUIState(row, _Controller.IsLocked);
		}

		protected abstract bool _RequestRemove();
		protected abstract void _ApplyFilter(string p);
		protected abstract List<T> _LoadEntity();
		protected abstract void _RemoveEntity(int id);
		protected virtual void _CreateDataTable()
		{
			if (_DtTable == null)
			{
				_DtTable = new DataTable();
				if (!_DedaColumns.IsNullOrEmpty())
					foreach(DedaGridColumn col in _DedaColumns)
						_DtTable.Columns.Add(col.DataColumn);
			}
			else
				_DtTable.Clear();
		}
		#endregion

		#region IRefreshable Members

		public void Reload(object sender, EventArgs<int> args)
		{
			_LoadData();

			if (StateModified != null && (int)args.Args > 0)
				StateModified(sender, args);
		}

		#endregion

		#region IStateModifier Members

		public event EventHandler<EventArgs<int>> StateModified;

		#endregion
	}
}
